package forum.server;


import forum.server.controller.ForumFacadeFactory;
import forum.server.controller.ForumFacadeInt;
import forum.server.controller.MyLogger;
import forum.server.domain.LoggedInUser;
import forum.server.domain.PostContent;
import forum.shared.exceptions.*;
import forum.client.*;
import forum.shared.*;

import com.google.gwt.user.server.rpc.RemoteServiceServlet;


@SuppressWarnings("serial")
public class ForumServiceImpl extends RemoteServiceServlet implements ForumService {

	private ForumFacadeInt forum;
	private MyLogger log;
	
	public ForumServiceImpl() throws DatabaseException{
		forum = ForumFacadeFactory.getPipe();
		log = MyLogger.getInstance();
	}

	@Override
	public ServerResponse sendMsg(String msg) {
		log.logInfo("Received a message from client: " + msg);
		String[] msgParts = msg.split(Delimiters.MSG_PARTS);

		try {
			if (msgParts[0].equals("Register"))
				return doRegister(msgParts);
			
			if (msgParts[0].equals("Modify"))
				return doModify(msgParts);
			
			if (msgParts[0].equals("Delete"))
				return doDelete(msgParts);
			
			if (msgParts[0].equals("Tree"))
				return doViewForum();
			
			if (msgParts[0].equals("Search"))
				return doSearch(msgParts);
			
			if (msgParts[0].equals("Login"))
				return doLogin(msgParts);
			
			if (msgParts[0].equals("Logoff"))
				return doLogoff();
			
			if(msgParts[0].equals("AddPost"))
				return doAddPost(msgParts);
			
			if (msgParts[0].equals("OnlineUsers"))
				return doGetOnlineUsers();
			
			if (msgParts[0].equals("AddReply"))
				return doAddReply(msgParts);
			
			if (msgParts[0].equals("Connect"))
				return doConnect();
			
			if (msgParts[0].equals("Disconnect"))
				return doDisconnect(msgParts);
			
			if (msgParts[0].equals("PromoteList"))
				return doGetPromoteList();
			
			if (msgParts[0].equals("DemoteList"))
				return doGetDemoteList();
			
			if (msgParts[0].equals("Promote"))
				return doPromote(msgParts);
			
			if (msgParts[0].equals("Demote"))
				return doDemote(msgParts);
			
		} catch (Exception ex) {
			MyLogger.getInstance().logSevere("Exception while parsing msg " +
					"from client: " + ex.getMessage());
		}
		
		return null;
	}

	/**
	 * 
	 * @param msgParts
	 * @return
	 */
	private ServerResponse doDemote(String[] msgParts) {
		// web client allows only single selection.
		// the facade API requires an array of usernames.
		String arr[] = new String[1];
		arr[0] = msgParts[1];
		try {
			forum.demoteModerator(arr);
			return new ServerResponse("Successfully demoted the user from Moderator privlidges", true);
		} catch (NotLoggedInException e) {
			return new ServerResponse("Guests cannot demote other users from moderators. Please login.", false);
		} catch (UnauthorizedOpException e) {
			return new ServerResponse(e.getMessage(),false);
		} catch (NoSuchUserException e) {
			return new ServerResponse(e.getMessage(),false);
		} catch (DatabaseException e) {
			return new ServerResponse("The server is currently down for maintanance.\nPlease try again later.",false);
		}
	}

	/**
	 * 
	 * @param msgParts
	 * @return
	 */
	private ServerResponse doPromote(String[] msgParts) {
		// web client allows only single selection.
		// the facade API requires an array of usernames.
		String arr[] = new String[1];
		arr[0] = msgParts[1];
		try {
			forum.promoteModerator(arr);
			return new ServerResponse("Successfully granted the user Moderator privlidges", true);
		} catch (NotLoggedInException e) {
			return new ServerResponse("Guests cannot promote other users to moderators. Please login.", false);
		} catch (UnauthorizedOpException e) {
			return new ServerResponse(e.getMessage(),false);
		} catch (NoSuchUserException e) {
			return new ServerResponse(e.getMessage(),false);
		} catch (DatabaseException e) {
			return new ServerResponse("The server is currently down for maintanance.\nPlease try again later.",false);
		}
	}

	/**
	 * 
	 * @return
	 */
	private ServerResponse doGetDemoteList() {
		try {
			String res = "";
			for(String str : forum.getModerators())
				res += str + Delimiters.MSG_PARTS;
			return new ServerResponse(res, true);
		} catch (DatabaseException e) {
			return new ServerResponse("The server is currently down for maintanance.\nPlease try again later.",false);                      
		}
	}

	/**
	 * 
	 * @return
	 */
	private ServerResponse doGetPromoteList() {
		try {
			String res = "";
			for(String str : forum.getAllUsersForPromotion())
				res += str + Delimiters.MSG_PARTS;
			return new ServerResponse(res, true);
		} catch (DatabaseException e) {
			return new ServerResponse("The server is currently down for maintanance.\nPlease try again later.",false);                      
		}

	}

	/**
	 * 
	 * @param msgParts
	 * @return
	 */
	private ServerResponse doDelete(String[] msgParts) {
		try {
			int postId = Integer.parseInt(msgParts[1]);
            forum.deletePost(postId);
            return new ServerResponse("The post #"+postId+" was successfully deleted", true);
        } catch (UnauthorizedOpException e) {
        	return new ServerResponse(e.getMessage(), false);
        } catch (NotLoggedInException e) {
                return new ServerResponse("Guests cannot delete posts. Please login.", false);
        } catch (NoSuchPostException e) {
                return new ServerResponse("No such post - can't delete.", false);
        } catch (DatabaseException e) {
                return new ServerResponse("The server is currently down for maintanance.\nPlease try again later.",false);
    	}
	}

	/**
	 * 
	 * @return
	 */
	private ServerResponse doConnect() {
		try {
			forum.incGuestCount();
		} catch (Exception e) {
			return new ServerResponse("Databse error.", false);
		}
		return new ServerResponse("Succefully connected guest.", true);
	}

	/**
	 * 
	 * @param msgParts
	 * @return
	 */
	private ServerResponse doDisconnect(String[] msgParts) {
		try {
			if (msgParts.length <= 1 || msgParts[1].isEmpty()) {
				forum.decGuestCount();
				return new ServerResponse("Succefully disconnected guest.", true);
			}
			else { // 
				forum.logoff();
				forum.decGuestCount();
				return new ServerResponse("Succefully disconnected user: " + msgParts[1], true);
			}
		} catch (Exception e) {
			return new ServerResponse("Databse error.", false);
		}
	}

	/**
	 * 
	 * @param msgParts
	 * @return
	 */
	private ServerResponse doAddReply(String[] msgParts) {
        try {
            forum.replyToPost(Integer.parseInt(msgParts[1]), msgParts[2], 
            		new PostContent(msgParts.length >= 4 ? msgParts[3] : ""));
            return new ServerResponse("The reply to message "+msgParts[1]+ 
            		" was successfully posted.", true);
	    } catch (NotLoggedInException e) {
	            return new ServerResponse("Guests are not allowed to reply to posts. " +
	            		"Please login.", false);
	            
	    } catch (NoSuchPostException e) {
	            return new ServerResponse("The post "+msgParts[1]+
	            		" does not exist.", false);               
	    } catch (DatabaseException e) {
	            return new ServerResponse("The server is currently down " +
	            		"for maintanance.\nPlease try again later.",false);
	    }

	}

	/**
	 * 
	 * @param msgParts
	 * @return
	 */
	private ServerResponse doModify(String[] msgParts) {
		try {
			forum.modifyPost(Integer.parseInt(msgParts[1]), new PostContent(msgParts[2]));
			return new ServerResponse("The post #"+ msgParts[1] +" was successfully modified", true);
		} 
		catch (UnauthorizedOpException e) {
			return new ServerResponse(e.getMessage(), false);
		} 
		catch (NotLoggedInException e) {
			return new ServerResponse("Guests cannot modify posts. Please login.", false);
		} 
		catch (NoSuchPostException e) {
			return new ServerResponse(e.getMessage(), false);
		} 
		catch (DatabaseException e) {
			return new ServerResponse("The server is currently down for maintanance.\nPlease try again later.",false); 
		}	
	}

	/**
	 * 
	 * @return
	 */
	private ServerResponse doGetOnlineUsers() {
		String users = "";

		try {
			for (String u : forum.getConnectedUsers())
				users += u + Delimiters.MSG_PARTS;

			return new ServerResponse(users + 
					forum.getGuestCount() + " guests", true);
		} catch (DatabaseException ex) {
			return new ServerResponse("Database error.", false);
		}
	}

	/**
	 * 
	 * @return
	 */
	private ServerResponse doLogoff() {
		forum.logoff();
		return new ServerResponse("Bye Bye.",true);
	}
	
	private ServerResponse doAddPost(String[] msgParts) {
		try {
			forum.addPost(msgParts[1], new PostContent(msgParts.length >= 3 ? msgParts[2] : ""));
			return new ServerResponse("The post was added successfully",true);
		}
		catch (NotLoggedInException e) {
			return new ServerResponse("Guests are not allowed to add posts.\n" +
					"Please login.",false);
		} catch (DatabaseException e) {
			return new ServerResponse("The server is currently down for maintanance.\n" +
					"Please try again later.",false);
		}
	}

	/**
	 * @param msgParts
	 * @return
	 */
	private ServerResponse doLogin(String[] msgParts) {
		//Taken from the do operation of the LoginMessage class.
		log.logInfo("Received a login message from " + msgParts[1]);
		try {
			LoggedInUser tUser = forum.login(msgParts[1], msgParts[2]);
			int permission=0;
			switch (tUser.getPermission()) {
			case ADMIN:
				permission=3;
				break;
			case MODERATOR:
				permission=2;
				break;
			case LOGGEDINUSER:
				permission=1;
				break;
			default:
				permission=0;
				break;
			}
			return new ServerResponse("Successfully logged in as: \""+msgParts[1]+"\""+" with permission "+permission ,true);
		} catch (IncorrectLoginException e) {
			return new ServerResponse(e.getMessage(),false);
		} catch (NoSuchUserException e) {
			return new ServerResponse("Username doesn't exist.",false);
		} catch (DatabaseException e) {
			return new ServerResponse("The server is currently down for maintanance.\nPlease try again later.",false);
		}
	}

	/**
	 * @param msgParts
	 * @return
	 */
	private ServerResponse doSearch(String[] msgParts) {
		if (msgParts[1].equals("AUTHOR"))
			try {
				return new ServerResponse(forum.searchByAuthor(msgParts[2],
						Integer.parseInt(msgParts[3]), 
						Integer.parseInt(msgParts[4])), true);
			} catch (NoSuchUserException e) {
				return new ServerResponse(e.getMessage(), false);
			} catch (InvalidSearchRangeException e) {
				return new ServerResponse(e.getMessage(), false);
			}
		if (msgParts[1].equals("CONTENT"))
			try {
				return new ServerResponse(forum.searchByContent(msgParts[2],
						Integer.parseInt(msgParts[3]), 
						Integer.parseInt(msgParts[4])), true);
			} catch (InvalidSearchRangeException e) {
				return new ServerResponse(e.getMessage(), false);
			}
			
		return null; // invalid 2nd arg
	}

	/**
	 * @return
	 */
	private ServerResponse doViewForum() {
		//Taken from the do operation of the View Forum class.
		String forumView = "";
		try {
			forumView = forum.viewForum();
		} catch (DatabaseException e) {
			return new ServerResponse("The server is currently down for maintanance.\n" +
		            "Please try again later.", false);
		}
		return new ServerResponse(forumView, true);
	}

	/**
	 * @param msgParts
	 * @return
	 */
	private ServerResponse doRegister(String[] msgParts) {
		//Taken from the do operation of the Register class.
		try {
			forum.register(msgParts[1], msgParts[2]);
			return new ServerResponse("Successfully registered \""+msgParts[1]+"\"",true);
		} 
		catch (RegistrationException e) {
			return new ServerResponse(e.getMessage(),false);
		} 
		catch (DatabaseException e) {
			return new ServerResponse("The server is currently down for maintanance.\n" +
					"Please try again later.",false);
		}
	}
}
